package com.justenholter.text {
	
	import com.justenholter.text.TextEffectManager;
	import com.justenholter.text.effects.IEffect;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.TimerEvent;
	import flash.text.TextField;
	import flash.utils.Timer;
	
	/**
	 * Transitions a TextFields.text property to
	 * a new value over time.
	 * 
	 * @author justen holter
	 */
	public class TextEffect extends EventDispatcher {
		
		private var _effect				:IEffect;
		private var _delay				:Number;
		private var _timer				:Timer;
		private var _target				:TextField;
		private var _text				:String
		private var _speed				:Number;
		
		/**
		 * Instance of IEffect.
		 */
		public function get effect():IEffect {
			return _effect;
		}
		
		/**
		 * Time in milliseconds to delay the effect.
		 */
		public function get delay():Number {
			return _delay;
		}
		
		/**
		 * The target TextField.
		 */
		public function get target():TextField {
			return _target;
		}
		
		/**
		 * Target text.
		 */
		public function get text():String {
			return _text;
		}
		
		/**
		 * Update speed in milliseconds.
		 */
		public function get speed():Number {
			return _speed;
		}
		
		/**
		 * If the TextEffect is currently running.
		 */
		public function get isRunning():Boolean {
			return _target.text != _text;
		}
		
		/**
		 * Creates a new instance of TextEffect.
		 * 
		 * @param	target		Target TextField.
		 * @param	text		Target text.
		 * @param	effect		Instance of IEffect.
		 * @param	speed		Update speed in milliseconds.
		 * @param	delay		Time in milliseconds to delay the effect.
		 */
		public function TextEffect(target:TextField, text:String, effect:IEffect, speed:Number = 50, delay:Number = 0){
			
			TextEffectManager.add(this);
			
			_target = target;
			_text = text;
			_effect = effect;
			_speed = speed;
			_delay = delay;
			_timer = new Timer(_delay);
			_timer.addEventListener(TimerEvent.TIMER, start);
			_timer.start();
		}
		
		private function start(event:TimerEvent):void {
			
			var temp:String = _target.text;
			_target.text = _effect.init(_target.text, _text);
			
			if(_target.text != _text){
				_timer.delay = _speed;
				_timer.removeEventListener(TimerEvent.TIMER, start);
				_timer.addEventListener(TimerEvent.TIMER, write);
				
				dispatchEvent( new Event(Event.CHANGE) );
				
			}else {
				if (temp != _text) dispatchEvent( new Event(Event.CHANGE) );
				dispatchEvent( new Event(Event.COMPLETE) );
				stop();
			}
		}
		
		private function write(event:TimerEvent):void {
			
			if(_target.text != _text){
				
				_target.text = _effect.next(_target.text, _text); 
				dispatchEvent(new Event(Event.CHANGE));
				
				if (_target.text == _text) {
					dispatchEvent( new Event(Event.COMPLETE) );
					stop();
				}
				
			}else{
				
				dispatchEvent(new Event(Event.COMPLETE));
				stop();
			}
		}
		
		/**
		 * Stop the text effect.
		 */
		public function stop():void {
			
			_timer.stop();
			_timer.removeEventListener(TimerEvent.TIMER, write);
			TextEffectManager.remove(this);
		} 
	}
}